using ImageCSharp.Core.Interfaces;
using ImageCSharp.Core.Models;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.IO;

namespace ImageCSharp.Core.Services
{
    /// <summary>
    /// 批处理服务实现
    /// </summary>
    public class BatchProcessingService : IBatchProcessingService, IDisposable
    {
        private readonly IImageService _imageService;
        private readonly IPluginService _pluginService;
        private CancellationTokenSource? _cancellationTokenSource;
        private BackgroundWorker? _backgroundWorker;

        public BatchProcessingConfiguration Configuration { get; set; } = new();

        public event EventHandler<BatchProgressEventArgs>? ProgressChanged;
        public event EventHandler<BatchCompletedEventArgs>? BatchCompleted;

        public BatchProcessingService(IImageService imageService, IPluginService pluginService)
        {
            _imageService = imageService;
            _pluginService = pluginService;
        }

        public void StartBatchProcessing(string inputDirectory, string outputDirectory)
        {
            if (!Directory.Exists(inputDirectory))
                throw new DirectoryNotFoundException($"Input directory not found: {inputDirectory}");

            Directory.CreateDirectory(outputDirectory);

            _cancellationTokenSource = new CancellationTokenSource();
            var token = _cancellationTokenSource.Token;

            _backgroundWorker = new BackgroundWorker();
            _backgroundWorker.DoWork += (sender, e) =>
            {
                ProcessImages(inputDirectory, outputDirectory, token);
            };
            _backgroundWorker.RunWorkerCompleted += (sender, e) =>
            {
                if (e.Error != null)
                {
                    OnBatchCompleted(new BatchCompletedEventArgs
                    {
                        ProcessedCount = 0,
                        FailedCount = 1,
                        ProcessingTime = TimeSpan.Zero,
                        FailedFiles = new List<string> { "Background worker error" }
                    });
                }
            };
            _backgroundWorker.RunWorkerAsync();
        }

        public void CancelBatchProcessing()
        {
            _cancellationTokenSource?.Cancel();
        }

        public BatchProcessingStatus GetStatus()
        {
            return new BatchProcessingStatus
            {
                IsRunning = _backgroundWorker?.IsBusy ?? false,
                ProcessedCount = 0, // 将在处理过程中更新
                TotalCount = 0,
                CurrentFile = string.Empty,
                StartTime = DateTime.Now
            };
        }

        private void ProcessImages(string inputDirectory, string outputDirectory, CancellationToken cancellationToken)
        {
            var imageExtensions = new[] { ".jpg", ".jpeg", ".png", ".bmp", ".gif", ".tiff", ".tif" 
            };

            var imageFiles = Directory.GetFiles(inputDirectory, "*.*", SearchOption.AllDirectories)
                .Where(file => imageExtensions.Contains(Path.GetExtension(file).ToLower()))
                .ToList();

            var processedCount = 0;
            var failedCount = 0;
            var failedFiles = new List<string>();
            var startTime = DateTime.Now;

            try
            {
                // 使用并行处理提高性能
                var parallelOptions = new ParallelOptions
                {
                    MaxDegreeOfParallelism = Configuration.MaxDegreeOfParallelism,
                    CancellationToken = cancellationToken
                };

                Parallel.ForEach(imageFiles, parallelOptions, imageFile =>
                {
                    if (cancellationToken.IsCancellationRequested)
                        return;

                    try
                    {
                        ProcessSingleImage(imageFile, inputDirectory, outputDirectory);
                        Interlocked.Increment(ref processedCount);
                        
                        OnProgressChanged(new BatchProgressEventArgs
                        {
                            ProcessedCount = processedCount,
                            TotalCount = imageFiles.Count,
                            CurrentFile = Path.GetFileName(imageFile)
                        });
                    }
                    catch (Exception ex)
                    {
                        Interlocked.Increment(ref failedCount);
                        lock (failedFiles)
                        {
                            failedFiles.Add($"{imageFile}: {ex.Message}");
                        }
                    }
                });
            }
            catch (OperationCanceledException)
            {
                // 处理被取消
            }

            var endTime = DateTime.Now;
            var processingTime = endTime - startTime;

            OnBatchCompleted(new BatchCompletedEventArgs
            {
                ProcessedCount = processedCount,
                FailedCount = failedCount,
                ProcessingTime = processingTime,
                FailedFiles = failedFiles
            });
        }

        private void ProcessSingleImage(string inputFile, string inputDirectory, string outputDirectory)
        {
            var relativePath = Path.GetRelativePath(inputDirectory, inputFile);
            var outputFile = Path.Combine(outputDirectory, relativePath);
            var outputFileDir = Path.GetDirectoryName(outputFile);

            if (!Directory.Exists(outputFileDir))
                Directory.CreateDirectory(outputFileDir!);

            // 如果文件已存在且不覆盖，则跳过
            if (File.Exists(outputFile) && !Configuration.OverwriteExisting)
                return;

            // 加载图像
            var document = _imageService.LoadImage(inputFile);

            // 应用插件
            foreach (var plugin in Configuration.Plugins)
            {
                if (plugin is IFilterPlugin filterPlugin)
                {
                    _imageService.ApplyFilter(document, filterPlugin);
                }
                else
                {
                    _pluginService.ExecutePlugin(plugin, document);
                }
            }

            // 调整大小
            if (Configuration.ResizeImages)
            {
                _imageService.ResizeImage(document, Configuration.TargetWidth, Configuration.TargetHeight);
            }

            // 格式转换
            if (Configuration.ConvertFormat)
            {
                var newExtension = $".{Configuration.TargetFormat.ToLower()}";
                outputFile = Path.ChangeExtension(outputFile, newExtension);
            }

            // 保存
            _imageService.SaveImage(document, outputFile);
        }

        protected virtual void OnProgressChanged(BatchProgressEventArgs e)
        {
            ProgressChanged?.Invoke(this, e);
        }

        protected virtual void OnBatchCompleted(BatchCompletedEventArgs e)
        {
            BatchCompleted?.Invoke(this, e);
        }

        public void Dispose()
        {
            _cancellationTokenSource?.Dispose();
            _backgroundWorker?.Dispose();
        }
    }
}